package com.kcnet.qk.netty;

import android.util.Log;

import com.kcnet.qk.constant.Const;
import com.kcnet.qk.util.PreferenceHelper;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * Netty客户端
 * Created by LiuSaibao on 11/23/2016.
 */
public class NettyClient {

	private static NettyClient nettyClient = new NettyClient();

	private EventLoopGroup group;

	private NettyListener listener;

	private Channel channel;
	
	private boolean isConnect = false;

	private int reconnectNum = Integer.MAX_VALUE;

	private long reconnectIntervalTime = 10000;
	
	public static NettyClient getInstance(){
		return nettyClient;
	}
	
	public   NettyClient connect() {


		try {
			Log.d("NettyService","synchronized connect");
			disconnect();
			//配置客户端的NIO线程组
			group = new NioEventLoopGroup();
			Bootstrap b = new Bootstrap();
			b.group(group)
					.channel(NioSocketChannel.class)
					.option(ChannelOption.TCP_NODELAY, true)
					.handler(new NettyClientInitializer(listener));


			//发生异步连接操作
			ChannelFuture f = b.connect(PreferenceHelper.getString(Const.HOST,""), Const.TCP_PORT).addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture channelFuture) throws Exception {
					if (channelFuture.isSuccess()) {
						isConnect = true;
						channel = channelFuture.channel();
					} else {
						isConnect = false;
					}
				}
			}).sync();
			//等待客户端链路关闭
			f.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
			if(listener!=null)listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_ERROR);
		} finally {
			try {
				if(group!=null)group.shutdownGracefully();
			}catch (Exception e){}
			//优雅退出，释放NIO线程组

		}


		return this;
	}

	public void disconnect() {
		if(group!=null)group.shutdownGracefully();
	}

	public void reconnect() {
		if(reconnectNum >0){
			reconnectNum--;
			try {
				Thread.sleep(reconnectIntervalTime);
			} catch (InterruptedException e) {}
			Log.e("NettyService","重新连接");
			disconnect();
			connect();
		}else{
			disconnect();
		}
	}
	public boolean sendMsgToServer(byte[] data) {
		boolean flag = channel != null && isConnect;
		if (flag) {

			ByteBuf heartBateBuf = Unpooled.buffer(data.length);
			heartBateBuf.writeBytes(data);
			channel.writeAndFlush(heartBateBuf).addListener(new ChannelFutureListener(){

				@Override
				public void operationComplete(ChannelFuture channelFuture) throws Exception {
					Log.d("NettyService","operationComplete "+channelFuture.isSuccess());
				}
			});
		}
		return flag;
	}


	public boolean senHartBoot(byte[] data) {
		boolean flag = channel != null && isConnect;
		if (flag) {

			ByteBuf heartBateBuf = Unpooled.buffer(data.length);
			heartBateBuf.writeBytes(data);
			channel.writeAndFlush(heartBateBuf).addListener(new ChannelFutureListener(){

				@Override
				public void operationComplete(ChannelFuture channelFuture) throws Exception {
					Log.d("NettyService","心跳数据发送 "+channelFuture.isSuccess());
				}
			});
		}
		return flag;
	}



	public boolean sendMsgToServer(byte[] data, ChannelFutureListener listener) {
		boolean flag = channel != null && isConnect;
		if (flag) {
			ByteBuf buf = Unpooled.copiedBuffer(data);
		channel.writeAndFlush(buf).addListener(listener);
	}
		return flag;
	}

	public boolean sendMsgToServer(ByteBuf data, ChannelFutureListener listener) {
		boolean flag = channel != null && isConnect;
		if (flag) {
			//ByteBuf buf = Unpooled.copiedBuffer(data);
			channel.writeAndFlush(data).addListener(listener);
		}
		return flag;
	}


	public void setReconnectNum(int reconnectNum) {
		this.reconnectNum = reconnectNum;
	}

	public void setReconnectIntervalTime(long reconnectIntervalTime) {
		this.reconnectIntervalTime = reconnectIntervalTime;
	}
	
	public boolean getConnectStatus(){
		return isConnect;
	}
	
	public void setConnectStatus(boolean status){
		this.isConnect = status;
	}
	
	public void setListener(NettyListener listener) {
		this.listener = listener;
	}
}
